<template>
    <a-layout>
        <a-layout-content
                :style="{ background: '#fff', padding: '24px', margin: 0, minHeight: '280px' }"
        >
            <a-row :gutter="24">
                <a-col :span="8">
                    <p>
                        <a-form layout="inline">
                            <a-form-item>
                                <a-button type="primary" @click="handleQuery()">查询</a-button>
                            </a-form-item>
                            <a-form-item>
                                <a-button type="primary" @click="handleAdd">新增</a-button>
                            </a-form-item>
                        </a-form>
                    </p>
                    <!-- 注1： 小技巧v-if="level1.length > 0"，因为默认展开属性defaultExpandAllRows不是动态监听数据变化的，而是表格初始时执行一次，后面就不再执行了， -->
                    <!--       用上面的小技巧，只有level1有数据了才去展示表格，此时defaultExpandAllRows属性就能起作用了 -->
                    <!-- 注2： 默认展开属性:defaultExpandAllRows前面加了冒号，后面就是boolean类型的true，不加冒号，后面就是一个字符串true -->
                    <a-table
                            v-if="level1.length > 0"
                            :columns="columns"
                            :data-source="level1"
                            :row-key="record => record.id"
                            :pagination="false"
                            :loading="loading"
                            size="small"
                            :defaultExpandAllRows="true"
                    >
                        <!-- 注意：列数据定义中，有指定dataIndex，则text为dataIndex对应的值；否则text与record完全一致 -->
                        <template #name="{ text, record }">
                            {{record.sort}} {{text}}
                        </template>
                        <template #action="{ text, record }">
                            <a-space size="small">
                                <a-button type="primary" @click="handleEdit(record)" size="small">编辑</a-button>
                                <a-popconfirm
                                        title="删除后不可恢复，确认删除?"
                                        ok-text="是"
                                        cancel-text="否"
                                        @confirm="handleDelete(record.id)"
                                >
                                    <!-- 在 2.2.0 之后，危险成为一种按钮属性而不是按钮类型 -->
                                    <a-button type="primary" danger size="small">删除</a-button>
                                </a-popconfirm>
                            </a-space>
                        </template>
                    </a-table>
                </a-col>
                <a-col :span="16">
                    <p>
                        <a-form layout="inline">
                            <a-form-item>
                                <a-button type="primary" @click="handleSave()">保存</a-button>
                            </a-form-item>
                        </a-form>
                    </p>
                    <a-form :model="doc" layout="vertical">
                        <a-form-item>
                            <a-input v-model:value="doc.name" placeholder="名称"/>
                        </a-form-item>
                        <a-form-item>
                            <!-- 树选择组件，:replaceFields进行字段名映射（默认取:tree-data中的title值作为显示、value作为选项对应值、key作为唯一标识、children作为子树名） -->
                            <a-tree-select
                                    v-model:value="doc.parent"
                                    style="width: 100%"
                                    :dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
                                    :tree-data="treeSelectData"
                                    placeholder="请选择父文档"
                                    tree-default-expand-all
                                    :replaceFields="{title: 'name', key: 'id', value: 'id'}"
                            >
                            </a-tree-select>
                        </a-form-item>
                        <a-form-item>
                            <a-input v-model:value="doc.sort" placeholder="顺序"/>
                        </a-form-item>
                        <a-form-item>
                            <a-button type="primary" @click="handlePreviewContent()">
                                <EyeOutlined/> 内容预览
                            </a-button>
                        </a-form-item>
                        <a-form-item>
                            <div id="content"/>
                        </a-form-item>
                    </a-form>
                </a-col>
            </a-row>
            <a-drawer
                    width="900"
                    placement="right"
                    :closable="false"
                    v-model:visible="drawerVisible"
            >
                <div class="wangeditor" :innerHTML="previewHtml"></div>
            </a-drawer>
        </a-layout-content>
    </a-layout>
    <!--<a-modal
      title="文档表单"
      v-model:visible="modalVisible"
      :confirm-loading="modalLoading"
      @ok="handleModalOk">

    </a-modal>-->
</template>

<script lang="ts">
import { defineComponent, onMounted, ref, createVNode } from 'vue';
import axios from 'axios';
import { message, Modal } from 'ant-design-vue';
import {Tool} from "@/util/tool";
import {useRoute} from "vue-router";
import { ExclamationCircleOutlined } from '@ant-design/icons-vue';
import E from 'wangeditor'

export default defineComponent({
  name: 'AdminDoc',
  setup() {
    const route = useRoute(); //vue内置的useRoute，通过这个函数可以得到route，借以得到路由的各种信息
    console.log("路由：", route);
    console.log("route.path：", route.path);
    console.log("route.query：", route.query);
    console.log("route.param：", route.params);
    console.log("route.fullPath：", route.fullPath);
    console.log("route.name：", route.name);
    console.log("route.meta：", route.meta);

    const loading = ref(false);
    /**
     * 一级文档树，children属性就是二级文档
     * [{
     *   id: "",
     *   name: "",'
     *   ...
     *   children: [{
     *     id: "",
     *     name: "",
     *     ...
     *   }]
     * }]
     */
    const level1 = ref(); // 一级文档树，children属性就是二级文档
    level1.value = [];       // 因为html中用到了level1.length，若不初始化一个空数组，页面加载时会报错

    // 因为树选择组件的属性状态，会随当前编辑的节点而变化，所以单独声明一个响应式变量（如：在level1里面添加一个"无"，则表格展示也会多出一个"无"）
    const treeSelectData = ref();
    treeSelectData.value = [];

    const columns = [
      {
        title: '名称',
        dataIndex: 'name',
        key: 'name',
        slots: { customRender: 'name' }
      },
      {
        title: 'Action',
        key: 'action',
        slots: { customRender: 'action' },
      },
    ];

    /** 数据查询 */
    const handleQuery = () => {
        loading.value = true;   // 加载中
        axios.get("/doc/all/" + route.query.ebookId).then((response) => {
            loading.value = false;  // 加载完成
            const data = response.data ;
            if(data.success){
                const docs = data.content ; //ref方式，赋值
                console.log("原始数组:" , docs) ;
                level1.value = Tool.array2Tree(docs, 0) ; // 父id为0，表示根节点，即一级文档
                console.log("树形结构:" , level1.value) ;

                // 父文档下拉框初始化，相当于点击新增【若当前电子书还没有文档，此时copy结果为undefined，则赋空值，避免下面添加元素报错，导致页面选不到“无”】
                treeSelectData.value = Tool.copy(level1.value) || [];   // 小技巧：前面没有值（如undefined），则取后面的空数组
                treeSelectData.value.unshift({id: 0, name: '无'});   // 为选择树添加一个"无"
            }else {
                message.error(data.message);
            }
        });
    };

    // ---- 表单 ----
    const doc = ref();
    doc.value = {
        ebookId: route.query.ebookId  // 初始时，就将路由传入的ebookId赋值给doc，以便直接点击保存按钮时，不会报电子书id为空的错误（因为文档编辑默认展示在后边了）
    } ;
    const editor = new E('#content') ;  // 富文本编辑器
    editor.config.zIndex = 0;   // 编辑器的z-index默认为10000，改为0，避免挡住上方父文档下拉框选项的展示

    /** 保存文档 */
    const handleSave = () => {
        doc.value.content = editor.txt.html() ; // 获取富文本
        axios.post("/doc/save", doc.value).then((response) => {
            const data = response.data ; // data = CommonResp
            // 后台返回成功后，关闭Modal弹框，并刷新列表
            if(data.success){
                message.success("保存成功！") ;
                // 重新加载列表（新增或编辑后）
                handleQuery();
            }else {
                message.error(data.message);
            }
        });
    }

    /** 将某节点及其子孙节点全部置为disabled */
    const setDisable = (treeSelectData: any, id: any) => {
        // console.log(treeSelectData, id);
        // 遍历数组，即遍历某一层节点
        for (let i = 0; i < treeSelectData.length; i++) {
          const node = treeSelectData[i];
          if (node.id === id) {
            // 如果当前节点就是目标节点
            console.log("disabled", node);
            // 将目标节点设置为disabled
            node.disabled = true;

            // 遍历所有子节点，将所有子节点全部都加上disabled
            const children = node.children;
            if (Tool.isNotEmpty(children)) {
              for (let j = 0; j < children.length; j++) {
                setDisable(children, children[j].id)
              }
            }
          } else {
            // 如果当前节点不是目标节点，则到其子节点再找找看。
            const children = node.children;
            if (Tool.isNotEmpty(children)) {
              setDisable(children, id);
            }
          }
        }
     };

    const deleteIds: Array<string> = [];
    const deleteNames: Array<string> = [];

    /** 查找整根树枝（treeSelectData:整个文档树数据, id:要删除的当前节点id） */
    const getDeleteIds = (treeSelectData: any, id: any) => {
        // 遍历数组，即遍历某一层节点
        for (let i = 0; i < treeSelectData.length; i++) {
            const node = treeSelectData[i] ;
            if(node.id === id){
                // 若当前节点就是目标节点，则将其id放入结果集
                deleteIds.push(id) ;
                deleteNames.push(node.name) ;
                // 遍历所有子节点，将所有子节点id也放入结果集
                const children = node.children ;
                if(Tool.isNotEmpty(children)){
                    for (let j = 0; j < children.length; j++) {
                        getDeleteIds(children, children[j].id) ;
                    }
                }
            }else {
                // 若当前节点不是目标节点，则到其子节点再找找看
                const children = node.children ;
                if(Tool.isNotEmpty(children)){
                    getDeleteIds(children, id) ;
                }
            }
        }
    };

    /** 文档内容查询（下面用到doc变量，所以不能放在doc变量申明的上面，否则会报变量未申明错误） */
    const handleQueryContent = () => {
        axios.get("/doc/find-content/" + doc.value.id).then((response) => {
            const data = response.data ;
            if(data.success){
                editor.txt.html(data.content) ; // 将后台返回的富文本内容，赋值到富文本编辑器中
            }else {
                message.error(data.message);
            }
        });
    };

    /** 编辑 */
    const handleEdit = (record: any) => {
        editor.txt.html("") ;    // 清空富文本框
        // record是响应式变量columns中的记录，直接复制给doc这个编辑框中的响应式变量，会导致编辑一半不保存直接关闭编辑框的情况下，columns中的记录也会跟着变化
        // doc.value = record ;
        doc.value = Tool.copy(record) ; // 用对象拷贝，解决响应式变量复制的影响
        handleQueryContent() ; // 根据doc.value.id，查询文档内容

        // 不能选择当前节点及其所有子孙节点，作为父节点，会使树断开
        treeSelectData.value = Tool.copy(level1.value);
        setDisable(treeSelectData.value, record.id);

        // 为选择树添加一个"无"
        treeSelectData.value.unshift({id: 0, name: '无'});
    }

    /** 新增 */
    const handleAdd = () => {
        editor.txt.html("") ;    // 清空富文本框
        doc.value = {
            ebookId: route.query.ebookId  // 弹出新增Modal时，将路由传入的ebookId赋值给doc中的属性，避免新增时后台非空报错
        } ;

        treeSelectData.value = Tool.copy(level1.value) || [];   // 小技巧：前面没有值（如undefined），则取后面的空数组（避免电子书没有文档时，下面的操作报错）
        // 为选择树添加一个"无"
        treeSelectData.value.unshift({id: 0, name: '无'});
    }

    /** 删除 */
    const handleDelete = (id: number) => {
        deleteIds.length = 0 ;  // 清空数组，否则多次删除时，数组会一直增加
        deleteNames.length = 0 ;
        getDeleteIds(level1.value, id) ; // 根据当前文档id，查找整根树枝【注意：这里用level1即可，不用treeSelectData，因为后者多一个"无"】
        Modal.confirm({
            title: () => '重要提示',
            icon: () => createVNode(ExclamationCircleOutlined),
            content: () => '将删除：【'+ deleteNames.join(",") +'】删除后不可恢复，确认删除？',
            onOk() {
                axios.delete("/doc/delete/" + deleteIds.join(",")).then((response) => {
                    const data = response.data ; // data = CommonResp
                    // 删除成功后，刷新列表
                    if(data.success){
                        handleQuery();
                    }else {
                        message.error(data.message);
                    }
                });
            },
        });
    }

    // ----------------富文本预览--------------
    const drawerVisible = ref(false) ;  // 预览抽屉页，初始默认不可见
    const previewHtml = ref() ;
    const handlePreviewContent = () => {
        previewHtml.value = editor.txt.html() ;
        drawerVisible.value = true ;
    };

    onMounted(() => {
        handleQuery() ;
        editor.create() ;   // 生成富文本编辑器
    });

    return {
      level1,
      columns,
      loading,
      handleQuery, // HTML中需要调用，所以要return出去

      handleEdit,
      handleAdd,
      handleDelete,

      doc,
      handleSave,
      treeSelectData,

      drawerVisible,
      previewHtml,
      handlePreviewContent
    };
  },

});
</script>

<style scoped>
    img {
        width: 50px;
        height: 50px;
    }
</style>